package cc.rengu.igas.opms.core.service.base;

import cc.rengu.igas.opms.common.constant.OpmsTreeNodeConstant;
import cc.rengu.igas.opms.common.enums.RespCodeEnum;
import cc.rengu.igas.share.common.constant.UserSessionConstant;
import cc.rengu.igas.share.core.model.MchntInfo;
import cc.rengu.igas.share.core.model.PlatMchntInfo;
import cc.rengu.igas.share.core.realize.MchntService;
import cc.rengu.igas.share.core.realize.UserService;
import cc.rengu.igas.share.core.realize.impl.MchntServiceImpl;
import cc.rengu.igas.share.core.realize.impl.RiskMonitorServiceImpl;
import cc.rengu.igas.share.core.realize.impl.UserServiceImpl;
import cc.rengu.oltp.service.base.BizBaseService;
import cc.rengu.oltp.service.model.RiskMonitorInfo;
import cc.rengu.oltp.service.common.constant.TreeNodeConstant;
import cc.rengu.oltp.service.common.dao.FinanceTxnMapper;
import cc.rengu.oltp.service.common.dao.impl.FinanceTxnMapperImpl;
import cc.rengu.oltp.service.common.entity.FinanceTxn;
import cc.rengu.oltp.service.common.enums.TransStatusEnum;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.model.BizResponse;
import cc.rengu.oltp.service.realize.RiskMonitorService;
import cc.rengu.oltp.utility.annotation.BIZ_AFTER;
import cc.rengu.oltp.utility.annotation.BIZ_BEFORE;
import cc.rengu.oltp.utility.annotation.BIZ_PROCESS;
import cc.rengu.oltp.utility.util.StringUtil;
import cc.rengu.oltp.utility.util.XmlTreeUtil;

/**
 * 业务撤销服务基类
 * Created by 王成 on 2018/4/17.
 */
public abstract class CancelService extends BizBaseService {
    public PlatMchntInfo platMchntInfo = null;
    public MchntInfo mchntInfo = null;

    @Override
    protected Object beforeBizProcess() throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        /* Step1：查找BIZ_BEFORE的注解 */
        invokeBizAnnoMethod(BIZ_BEFORE.class);

        /* Step2：检查平台商户状态 */
        MchntService mchntService = new MchntServiceImpl();
        String instId = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.INST_ID);
        String platMchntNo = xmlTreeUtil.getXmlTreeStringValue(OpmsTreeNodeConstant.PLAT_MCHNT_NO);
        if (!StringUtil.isEmptyOrNull(platMchntNo)) {
            /* 校验交易接口中的商户号与会话中的商户号是否一致 */
            UserService userService = new UserServiceImpl();
            String transMchntNo = userService.getUserSessionValue(UserSessionConstant.PLAT_MCHNT_NO);
            if (!StringUtil.isEmptyOrNull(transMchntNo) && !platMchntNo.equals(transMchntNo)) {
                rglog.error("交易请求上送的商户<{}>与用户会话中商户号<{}>不一致!", platMchntNo, transMchntNo);
                throw new BizException(RespCodeEnum.MCHNT_DISACCORD.getRespCode(), RespCodeEnum.MCHNT_DISACCORD.getRespDesc());
            }
            if (!mchntService.checkPlatMchntStatus(instId, platMchntNo)) {
                rglog.error("平台商户<{}>状态异常!", platMchntNo);
                throw new BizException(RespCodeEnum.MCHNT_STATUS_ABNORMAL.getRespCode(), RespCodeEnum.MCHNT_STATUS_ABNORMAL.getRespDesc());
            }
            platMchntInfo = mchntService.getPlatMchntInfo(instId, platMchntNo);
            if (null == platMchntInfo) {
                rglog.error("查询平台商户基本信息失败<{}>", platMchntNo);
                throw new BizException(RespCodeEnum.MCHNT_INFO_NOT_FOUND.getRespCode(), RespCodeEnum.MCHNT_INFO_NOT_FOUND.getRespDesc());
            }
        }

        /* Step3：检查商户合法性 */
        String mchntNo = xmlTreeUtil.getXmlTreeStringValue(OpmsTreeNodeConstant.MCHNT_NO);
        if (!StringUtil.isEmptyOrNull(mchntNo)) {
            if (!mchntService.checkMchntStatus(instId, mchntNo)) {
                rglog.error("商户<{}>状态异常!", mchntNo);
                throw new BizException(RespCodeEnum.MCHNT_STATUS_ABNORMAL.getRespCode(), RespCodeEnum.MCHNT_STATUS_ABNORMAL.getRespDesc());
            }
            mchntInfo = mchntService.getMchntInfo(instId, mchntNo);
            if (null == mchntInfo) {
                rglog.error("查询商户基本信息失败<{}>", mchntNo);
                throw new BizException(RespCodeEnum.MCHNT_INFO_NOT_FOUND.getRespCode(), RespCodeEnum.MCHNT_INFO_NOT_FOUND.getRespDesc());
            }
        }

        /* Step4：校验原交易状态 */
        FinanceTxnMapper txnMapper = new FinanceTxnMapperImpl();
        FinanceTxn orgFinanceTxn = txnMapper.selectFinanceTxnInfoByPrimaryKey(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.INST_ID), "");
        if (null == orgFinanceTxn) {
            throw new BizException(RespCodeEnum.OPM_ORIG_TXN_NOT_FOUND.getRespCode(), RespCodeEnum.OPM_ORIG_TXN_NOT_FOUND.getRespDesc());
        } else {
            if (!TransStatusEnum.TRANS_SUCC.getStatus().equals(orgFinanceTxn.getTxnStatus())) {
                rglog.error("原交易已不成功，不允许做撤销操作!");
                throw new BizException(RespCodeEnum.ORDER_CANT_REFUND.getRespCode(), RespCodeEnum.ORDER_CANT_REFUND.getRespDesc());
            }

            /* 将原交易信息设置到内部树 */
            xmlTreeUtil.setXmlTreeObjectValue(OpmsTreeNodeConstant.ORIG_TXN_INFO, orgFinanceTxn);
        }

        /* Step5：交易处理前客户化 */
        return bizBeforeCust();
    }

    @Override
    protected BizResponse callBizService(Object request) throws Exception {
        /* Step1：公共业务处理 */

        /* Step2：查找BIZ_PROCESS的注解 */
        invokeBizAnnoMethod(BIZ_PROCESS.class);

        /* Step3：业务逻辑处理*/
        return bizProcessCust(request);
    }

    @Override
    protected void afterBizProcess(BizResponse response) throws Exception {
        /* Step1：业务调用后公共处理*/

        /* Step2：查找BIZ_AFTER的注解 */
        invokeBizAnnoMethod(BIZ_AFTER.class);

        /* Step3：业务调用后客户化处理 */
        bizAfterCust(response);
    }

    @Override
    protected RiskMonitorInfo getRiskMonitorInfo() {
        RiskMonitorInfo riskMonitorInfo = new RiskMonitorInfo();
        RiskMonitorService riskMonitorService = new RiskMonitorServiceImpl();
        riskMonitorInfo.setTransMonitor(riskMonitorService);
        return riskMonitorInfo;
    }

    /**
     * 业务处理前客户化处理
     *
     * @return 业务处理实体类
     */
    protected abstract Object bizBeforeCust() throws Exception;

    /**
     * 业务逻辑处理客户化处理
     *
     * @param request 业务处理前的返回实体类
     * @return 业务处理结果
     */
    protected abstract BizResponse bizProcessCust(Object request) throws Exception;

    /**
     * 业务处理后逻辑处理
     *
     * @param response 业务调用响应信息
     */
    protected abstract void bizAfterCust(Object response) throws Exception;
}
